/* 
 * File:   main.cpp
 * Author: Luis
 *
 * Created on 26 de Abril de 2011, 07:14
 */

#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <set>
#include <stdio.h>
#include <stdlib.h>

#include <math.h>
#include <string>
#include <cstring>
#include <time.h>
#include "Ponto.h"
#include "Octree.h"
#include "Timer.h"

using namespace std;

/**
 * função que trata a saída do nome
 */
const char*argName(char** argv)
{
    //É verificado se o argumento passado é diferente das opções oferecidas pelo programa caso sim saimos
    if (argv[1][1]!='x' && argv[1][1]!='f')
    {
        cout << "Parametro inexistente" << endl;
        exit(1);
    }

    // usado para descobrir o tamanho do nome do arquivo
    size_t tamArgv2;
    // extraimos o tamanho do nome
    tamArgv2 = strlen(argv[2]);
    // criamos uma string com o nome do arquivo, isso será utilizado para criar o nome do arquivo de saida
    string nomeArquivo(argv[2]);
    // extraimos o threshold como string para adicionar ao nome do arquivo
    string S_threshold(argv[4]);
    // iserimos o threshold como texto no nome do arquivo final logo antes do ponto que antecede a extensao do arquivo
    nomeArquivo.insert(tamArgv2-4,S_threshold);
    // se o parametro passado foi x a extensao final será xyz
    if (argv[1][1]=='x')
    {
        nomeArquivo[nomeArquivo.length() -1] = 'z';
        nomeArquivo[nomeArquivo.length() -2] = 'y';
        nomeArquivo[nomeArquivo.length() -3] = 'x';
    }

    // retornamos o nome final do arquivo de saida
    return nomeArquivo.data();
}

/**
 * Mostra arquivo de ajuda em tela
 */
void help(string arqHelp)
{
    //gera um stream para o arquivo de texto
    ifstream arquivoHelp(arqHelp.c_str());
    string linha; // opera como buffer

    // enquanto não chegar ao final do arquivo
    while (!arquivoHelp.eof())
    {

        std::getline(arquivoHelp, linha); // grava a linha no buffer
        cout << linha << endl; // exibe em tela

    } // end while

    arquivoHelp.close();	// fecha o arquivo de ajuda
} // end arqHelp

/**
 * Leitura do arquivo e geração dos pontos
 */


/*
 * Função Principal do Programa
 */
int main(int argc, char** argv) {

    //Cria objeto Timer;
    Timer tempo;

    //Incia a contagem de tempo
    tempo.startTimer();
    
    // Verifica-se se foi pedido o arquivo de ajuda
    if (argv[1][1]=='h')
    {
        help("arquivoAjuda.txt");
        return 1;
    }

    //É extraído o threshold 
    float Threshold = atof(argv[4]);

    // declaramos as variaveis que irão representar nossos arquivos em memória
    FILE *fileOUT;
    FILE *fileIN;

    // obtemos o nome do arquivo que será carregado na memória
    char *Filename = argv[2];

    // usamos a função fopen para carregar a nuvem de pontos
    fileIN=fopen(Filename,"r"); //abre o arq. p/ leitura
    if(fileIN == NULL){
        cout << "Arquivo de entrada invalido "<<endl;
        exit(1);
    }
    
    //chamamos a funçã argName que retornará o nome do arquivo a ser salvo conforme o parametro que foi dado
    fileOUT=fopen(argName(argv),"w");
    if(fileIN == NULL){
        cout << "Problema no arquivo de saída "<<endl;
        exit(1);
    }
    
    // criamos variáveis auxiliares para criação de um objeto ponto conforme for feita a leitura do arquivo
    Ponto *novoPonto;
    float x,y,z;
    int cc,conf;

    Octree octree;
    //é setado o threshold na árvore
    octree.setThreshold(Threshold);

    //é realizado o calculo do número de níveis
    octree.calculoNiveis();

    //É iniciada a leitura do arquivo até atingir o fim
    while (!feof(fileIN))
    {
        //lê o arquivo e passa seus valores para as variaveis respectivas.
        fscanf(fileIN, "%f %f %f %d %d\n", &x, &y, &z, &cc, &conf);
        //Cria objeto ponto
        novoPonto = new Ponto(x, y, z, cc, conf);
        //Realiza a inserção do ponto na árvore
        octree.Insercao(novoPonto);
    }
    // terminado o loop principal fechamos os arquivos
    fclose(fileIN);
    fclose(fileOUT);


    cout<<"Tempo da operação: " << tempo.stopTimer() <<endl;

    return (EXIT_SUCCESS);
}


